package org.groupg.mockdatabyspring.morkdata.model.DBInfo;

import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.Getter;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.Serializable;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 数据库表信息内容
 */
@Data
public class DBTableInfo implements Serializable {

    /**
     * 表名
     */
    private String tableName;
    /**
     * 模式名
     */
    private String schemaName;
    /**
     * 用户名
     */
    private String username;

    /**
     * 表说明
     */
    private String comment;


    /**
     * 该表拥有的子字段
     */
    @Getter
    private Queue<DBColumnInfo> columnInfos;

    /**
     * 默认创建对象的方法
     *
     * @param tableName  表名
     * @param schemaName 模式名
     * @param username   用户名
     * @param comment    表说明
     */
    public DBTableInfo(@NotNull(message = "表名不能为空！") String tableName, @NotNull(message = "模式名不能为空！") String schemaName, @NotNull(message = "用户名不能为空！") String username, String comment) {
        this.tableName = tableName;
        this.schemaName = schemaName;
        this.username = username;
        // 避免序列化问题
        this.columnInfos = new ConcurrentLinkedQueue<>();
        this.comment = comment;
    }

    /**
     * 根据每个字段的正则模板创建字符串行
     *
     * @param fieldSplit 字段分隔符
     * @return 返回行字符串
     */
    public String getLineString(String fieldSplit) {
        StringBuilder sbr = new StringBuilder();
        for (DBColumnInfo dbColumnInfo : columnInfos) {
            sbr.append(dbColumnInfo.getRandomString());
            sbr.append(fieldSplit);
        }
        sbr.setLength(sbr.length() - 1);
        return sbr.toString();
    }

    /**
     * 创建标题字符串
     *
     * @param fieldSplit 字段分隔符
     * @return 返回标题字符串
     */
    public String getTitleString(String fieldSplit) {
        StringBuilder sbr = new StringBuilder();
        for (DBColumnInfo dbColumnInfo : columnInfos) {
            sbr.append(dbColumnInfo.getColumnName());
            sbr.append(fieldSplit);
        }
        sbr.setLength(sbr.length() - 1);
        return sbr.toString();
    }

    /**
     * 添加字段信息
     *
     * @param columnName        字段名称
     * @param columnType        字段类型
     * @param isPK              是否主键
     * @param isNullAble        是否可以为空
     * @param dataMaxIntLength  整数位长度
     * @param dataDecimalLength 小数位长度
     * @param strTmpId          生成正则内容
     * @param comment           字段说明
     * @return 当前对象
     */
    public DBTableInfo addColumnInfo(String columnName, String columnType
            , boolean isPK
            , boolean isNullAble
            , Integer dataMaxIntLength
            , Integer dataDecimalLength
            , String strTmpId
            , String comment) {

        this.getColumnInfos().add(new DBColumnInfo(tableName, schemaName, username, columnName, columnType, isPK, isNullAble, dataMaxIntLength, dataDecimalLength, strTmpId, comment));
        return this;
    }

    /**
     * 判断该表是否有该字段
     * @param columnInfo 字段属性
     * @return 是否存在
     */
    public boolean hasColumn(DBColumnInfo columnInfo){
        return this.columnInfos.contains(columnInfo);
    }

        /**
     * 判断该表是否有该字段
     * @param columnInfos 多个字段属性
     * @return 是否存在
     */
    public boolean hasColumn(List<DBColumnInfo> columnInfos){
        for (DBColumnInfo columnInfo : columnInfos){
            if (this.columnInfos.contains(columnInfo)){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据字段名找字段对象
     * @param columnName 字段名字
     * @return 该表的字段对象，若不存在则返回空
     */
    public DBColumnInfo getColumnInfo(String columnName){
        final DBColumnInfo[] columnInfo = {null};
        this.getColumnInfos().forEach(e -> {
            if (e.getColumnName().equals(columnName)){
                columnInfo[0] = e;
            };
        });
        return columnInfo[0];
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        DBTableInfo that = (DBTableInfo) o;

        return new EqualsBuilder().append(getTableName(), that.getTableName()).append(getSchemaName(), that.getSchemaName()).append(getUsername(), that.getUsername()).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37).append(getTableName()).append(getSchemaName()).append(getUsername()).toHashCode();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this)
                .append("tableName", tableName)
                .append("schemaName", schemaName)
                .append("username", username)
                .append("comment", comment)
                .append("columnInfos", columnInfos)
                .toString();
    }
}
